package com.vtuzx.kingdee.xqc_core.dao;

import com.mongodb.client.AggregateIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.vtuzx.core.db.mongo.impl.VtuzxDaoImpl;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 对接系统接口履历Dao
 */
@Component
public class OtherInDetailDao extends VtuzxDaoImpl {
    /** 集合名称 */
    public static final String NAME = "t_other_in_detail";

    public OtherInDetailDao() {
        super(NAME);
    }
    public Iterator<Document> findMaterialSummary(Criteria cond, Document sort, int pageIndex, int pageSize) {

        List<Document> allResults = new ArrayList<>();

        Document match = new Document("$match", cond.getCriteriaObject());
        Document sortDoc = sort != null ? sort : new Document("createTime", -1); // 默认按 materialNo 升序

        List<String> collections = Arrays.asList(
                OtherInDetailDao.NAME,
                PrdPickDetailDao.NAME,
                BatchAndExpDetailDao.NAME,
                PrdInDetailDao.NAME,
                PurInDetailDao.NAME,
                MaterialBomPickDetailDao.NAME,
                MaterialBomSupplementDetailDao.NAME,
                OtherOutDetailDao.NAME,
                SaleOutDetailDao.NAME,
                AllocationDetailDao.NAME
        );
        // 遍历集合，执行聚合查询，使用 iterator 取出每个集合的文档
        for (String collection : collections) {
            List<Document> pipeline = new ArrayList<>();
            pipeline.add(match);
            pipeline.add(new Document("$sort", sortDoc));
            // 返回 Iterator<Document>
            MongoCursor<Document> cursor = this
                    .getCollection(collection)
                    .aggregate(pipeline)
                    .allowDiskUse(true)
                    .iterator();

            while (cursor.hasNext()) {
                allResults.add(cursor.next());
            }
            cursor.close();
        }
        // 全局排序
        allResults.sort((d1, d2) -> {
            for (Map.Entry<String, Object> entry : sortDoc.entrySet()) {
                String field = entry.getKey();
                int direction = (int) entry.getValue(); // 1 升序，-1 降序
                Comparable v1 = d1.get(field, Comparable.class);
                Comparable v2 = d2.get(field, Comparable.class);
                if (v1 == null || v2 == null) continue;
                int cmp = v1.compareTo(v2);
                if (cmp != 0) return direction * cmp;
            }
            return 0;
        });

        // 分页
        //        if (pageIndex > 0 && pageSize > 0) {
//            docList.add(new Document("$skip", pageIndex * pageSize));
//        }
        int fromIndex = pageIndex * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, allResults.size());
        List<Document> paged = fromIndex < toIndex ? allResults.subList(fromIndex, toIndex) : Collections.emptyList();

        return paged.iterator();


//        List<Document> docList = new ArrayList<>();
//        docList.add(new Document("$group", new Document("_id", "any").append(OtherInDetailDao.NAME, new Document("$push","$$ROOT"))));
//        docList.add(new Document("$lookup", new Document("from", OtherInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", OtherInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", BatchAndExpDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", BatchAndExpDetailDao.NAME)));
//        //生产领料
//        docList.add(new Document("$lookup", new Document("from", PrdPickDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PrdPickDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PrdInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PrdInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PurInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PurInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", MaterialBomPickDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", MaterialBomPickDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", MaterialBomSupplementDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", MaterialBomSupplementDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", OtherOutDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", OtherOutDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", SaleOutDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", SaleOutDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", AllocationDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", AllocationDetailDao.NAME)));
//        docList.add(new Document("$project", new Document("_id", null).append("allValue", new Document("$setUnion", new VtuzxArrayList<>( "$" + OtherInDetailDao.NAME,"$"+PrdInDetailDao.NAME,
//                "$"+PrdPickDetailDao.NAME,
//                "$"+BatchAndExpDetailDao.NAME,
//                "$"+PurInDetailDao.NAME,"$"+MaterialBomPickDetailDao.NAME,"$" + MaterialBomSupplementDetailDao.NAME,"$"+OtherOutDetailDao.NAME,"$"+SaleOutDetailDao.NAME,"$"+AllocationDetailDao.NAME)))));
//        docList.add(new Document("$unwind", new Document("path", "$allValue")));
//        docList.add(new Document("$match", cond.getCriteriaObject()));
//        if ( sort != null){
//            docList.add(new Document("$sort",sort));
//        }
//        if (pageIndex > 0 && pageSize > 0) {
//            docList.add(new Document("$skip", pageIndex * pageSize));
//        }
//        if (pageSize > 0) {
//            docList.add(new Document("$limit", pageSize));
//        }
//        return this.aggregate(docList);
    }

    public int countFindMaterialSummary(Criteria cond) {
        List<String> detailCollections = Arrays.asList(
                OtherInDetailDao.NAME,
                PrdPickDetailDao.NAME,
                PrdInDetailDao.NAME,
                BatchAndExpDetailDao.NAME,
                PurInDetailDao.NAME,
                MaterialBomPickDetailDao.NAME,
                MaterialBomSupplementDetailDao.NAME,
                OtherOutDetailDao.NAME,
                SaleOutDetailDao.NAME,
                AllocationDetailDao.NAME
        );

        // 用于合并结果
        Map<String, Integer> totalCountMap = new HashMap<>();
        for (String collection : detailCollections) {
            List<Document> pipeline = new ArrayList<>();
            // 1. 先 match 条件
            pipeline.add(new Document("$match", cond.getCriteriaObject()));
            // 2. 再 group
            pipeline.add(new Document("$group", new Document("_id",
                    new Document("stockNo", "$stockNo").append("materialNo", "$materialNo"))
                    .append("count", new Document("$sum", 1))));
            // 3. 查询当前集合
            MongoCollection<Document> coll = this.getCollection(collection);
            AggregateIterable<Document> result = coll.aggregate(pipeline);
            // 4. 累加到总 map
            for (Document doc : result) {
                Document id = (Document) doc.get("_id");
                String key = id.getString("stockNo") + "_" + id.getString("materialNo");
                int count = doc.getInteger("count", 0);
                totalCountMap.merge(key, count, Integer::sum);
            }
        }
        // 示例：返回某个组合的 count，如果你要总和也可以 sum 所有 value
        int total = totalCountMap.values().stream().mapToInt(Integer::intValue).sum();
        return total;
        // 返回最终结果列表
//        return new ArrayList<>(groupMap.values());
//        List<Document> docList = new ArrayList<>();
//        docList.add(new Document("$group", new Document("_id", "any").append(OtherInDetailDao.NAME, new Document("$push", "$$ROOT"))));
//        docList.add(new Document("$lookup", new Document("from", OtherInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", OtherInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", BatchAndExpDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", BatchAndExpDetailDao.NAME)));
//        //生产领料
//        docList.add(new Document("$lookup", new Document("from", PrdPickDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PrdPickDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PrdInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PrdInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PurInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PurInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", MaterialBomPickDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", MaterialBomPickDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", MaterialBomSupplementDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", MaterialBomSupplementDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", OtherOutDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", OtherOutDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", SaleOutDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", SaleOutDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", AllocationDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", AllocationDetailDao.NAME)));
//        docList.add(new Document("$project", new Document("_id", null).append("allValue", new Document("$setUnion", new VtuzxArrayList<>( "$" + OtherInDetailDao.NAME,"$"+PrdInDetailDao.NAME,
//                "$"+PrdPickDetailDao.NAME,
//                "$"+BatchAndExpDetailDao.NAME,
//                "$"+PurInDetailDao.NAME,"$"+MaterialBomPickDetailDao.NAME,"$" + MaterialBomSupplementDetailDao.NAME,"$"+OtherOutDetailDao.NAME,"$"+SaleOutDetailDao.NAME,"$"+AllocationDetailDao.NAME)))));
//        docList.add(new Document("$unwind", new Document("path", "$allValue")));
//        docList.add(new Document("$match", cond.getCriteriaObject()));
//        docList.add(new Document("$group",
//                new Document("_id", new Document("stockNo","$stockNo").append("materialNo","$materialNo"))
//                        .append("count", new Document("$sum", 1))));
//        Iterator<Document> itr = this.aggregate(docList);
//        if (itr.hasNext()) {
//            return VtuzxUtil.getObject(itr.next(), "count");
//        }
//        return 0;
    }

    /**
     * 用于物料收发明细（所有入库表）计算期入
     * @param cond
     * @param
     * @return
     */
    public Iterator<Document> findInDetail(Criteria cond) {
        List<String> collections = Arrays.asList(
                OtherInDetailDao.NAME,
                BatchAndExpDetailDao.NAME,
                PrdInDetailDao.NAME,
                PurInDetailDao.NAME,
                AllocationDetailDao.NAME
        );

        // 前端传入的查询条件
        Document match = new Document("$match", cond.getCriteriaObject());

        // 最终结果集合（临时保存）
        List<Document> allResults = new ArrayList<>();

        for (String collection : collections) {
            List<Document> pipeline = new ArrayList<>();
            pipeline.add(match);

            MongoCursor<Document> cursor = this
                    .getCollection(collection)
                    .aggregate(pipeline)
                    .allowDiskUse(true)
                    .iterator();
            while (cursor.hasNext()) {
                allResults.add(cursor.next());
            }
            cursor.close();
        }
        // 最后返回结果的 Iterator<Document>
        return allResults.iterator();

//        List<Document> docList = new ArrayList<>();
//        docList.add(new Document("$group", new Document("_id", "any").append("tableA", new Document("$push", "$$ROOT"))));
//        docList.add(new Document("$lookup", new Document("from", OtherInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", OtherInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", BatchAndExpDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", BatchAndExpDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PrdInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PrdInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", PurInDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", PurInDetailDao.NAME)));
//        docList.add(new Document("$lookup", new Document("from", AllocationDetailDao.NAME).append("foreignField", "xxx1").append("localField", "xxx2").append("as", AllocationDetailDao.NAME)));
//        docList.add(new Document("$project", new Document("_id", null).append("allValue", new Document("$setUnion", new VtuzxArrayList<>("$tableA", "$" + OtherInDetailDao.NAME,"$"+PrdInDetailDao.NAME,
//                "$"+PurInDetailDao.NAME,
//                "$"+BatchAndExpDetailDao.NAME,
//                "$"+ AllocationDetailDao.NAME)))));
//        docList.add(new Document("$unwind", new Document("path", "$allValue")));
//        docList.add(new Document("$match", cond.getCriteriaObject()));
//        //docList.add(new Document("$match", cond.getCriteriaObject()));
//
//        return this.aggregate(docList);
    }
    public Iterator<Document> downloadFindMaterialSummary(Criteria cond, Document sort, int pageIndex, int pageSize) {

        List<Document> allResults = new ArrayList<>();

        Document match = new Document("$match", cond.getCriteriaObject());
        Document sortDoc = sort != null ? sort : new Document("createTime", -1); // 默认按 materialNo 升序

        List<String> collections = Arrays.asList(
                OtherInDetailDao.NAME,
                PrdPickDetailDao.NAME,
                BatchAndExpDetailDao.NAME,
                PrdInDetailDao.NAME,
                PurInDetailDao.NAME,
                MaterialBomPickDetailDao.NAME,
                MaterialBomSupplementDetailDao.NAME,
                OtherOutDetailDao.NAME,
                SaleOutDetailDao.NAME,
                AllocationDetailDao.NAME
        );
        // 遍历集合，执行聚合查询，使用 iterator 取出每个集合的文档
        for (String collection : collections) {
            List<Document> pipeline = new ArrayList<>();
            pipeline.add(match);
            pipeline.add(new Document("$sort", sortDoc));
            // 返回 Iterator<Document>
            MongoCursor<Document> cursor = this
                    .getCollection(collection)
                    .aggregate(pipeline)
                    .allowDiskUse(true)
                    .iterator();

            while (cursor.hasNext()) {
                allResults.add(cursor.next());
            }
            cursor.close();
        }
        // 全局排序
        allResults.sort((d1, d2) -> {
            for (Map.Entry<String, Object> entry : sortDoc.entrySet()) {
                String field = entry.getKey();
                int direction = (int) entry.getValue(); // 1 升序，-1 降序
                Comparable v1 = d1.get(field, Comparable.class);
                Comparable v2 = d2.get(field, Comparable.class);
                if (v1 == null || v2 == null) continue;
                int cmp = v1.compareTo(v2);
                if (cmp != 0) return direction * cmp;
            }
            return 0;
        });
        return allResults.iterator();
    }
}